﻿using System;
using System.Windows.Input;

namespace MvvmFx.Common.ViewModels.Commands
{
    /// <summary>
    /// A class that inherits from <see cref="CommandHandler{T}"/> and contains the functionality 
    /// to specify an action that should be invoked when either an instance of an <see cref="IViewModelCommand"/>
    /// is executed, or any instance of a specified concrete type of <see cref="IViewModelCommand"/>
    /// </summary>
    /// <remarks>
    /// A <see cref="CommandHandler"/> is like an <see cref="ICommand"/> in the sense that it
    /// encapsulates a unit of application logic that can be executed via an Execute method.
    /// It is used to specify a unit of code that should be executed when a certain <see cref="ICommand"/> 
    /// executes. 
    /// It can be registered to handle either a specific instance of a command, a Per-Instance Handler,
    /// or the execution of any instance of a specific type of command, a Per-Type Handler.
    /// </remarks>
 /// <typeparam name="T">The type of <see cref="IViewModelCommand"/> to handle</typeparam>
    public class ActionCommandHandler<T> : CommandHandler<T>
        where T : IViewModelCommand
    {
        #region Fields

        readonly Action<T, object> execute;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ActionCommandHandler&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="execute">The execute.</param>
        public ActionCommandHandler(Action<T, object> execute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");

            this.execute = execute;
        }

        #endregion

        #region [ Protected Overrides ]

        /// <summary>
        /// Override and implement the unit of logic to be executed.
        /// </summary>
        /// <param name="cmd">The command associated to the handler.</param>
        /// <param name="parameter">The parameter to pass to the unit of logic.</param>
        protected sealed override void OnExecute(T cmd, object parameter)
        {
            execute(cmd, parameter);
        }

        #endregion
    }

    /// <summary>
    /// A class that inherits from <see cref="CommandHandler{T}"/> and contains the functionality 
    /// to specify an action that should be invoked when either an instance of an <see cref="IViewModelCommand"/>
    /// is executed, or any instance of a specified concrete type of <see cref="IViewModelCommand"/>
    /// </summary>
    /// <remarks>
    /// A <see cref="CommandHandler"/> is like an <see cref="ICommand"/> in the sense that it
    /// encapsulates a unit of application logic that can be executed via an Execute method.
    /// It is used to specify a unit of code that should be executed when a certain <see cref="ICommand"/> 
    /// executes. 
    /// It can be registered to handle either a specific instance of a command, a Per-Instance Handler,
    /// or the execution of any instance of a specific type of command, a Per-Type Handler.
    /// </remarks>
    public class ActionCommandHandler : CommandHandler
    {
        #region Fields

        readonly Action<ICommand, object> execute;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ActionCommandHandler"/> class.
        /// </summary>
        /// <param name="execute">The execute.</param>
        public ActionCommandHandler(Action<ICommand, object> execute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");

            this.execute = execute;
        }

        #endregion

        #region [ Protected Overrides ]

        /// <summary>
        /// Override and implement the unit of logic to be executed.
        /// </summary>
        /// <param name="cmd">The command associated to the handler.</param>
        /// <param name="parameter">The parameter to pass to the unit of logic.</param>
        protected sealed override void OnExecute(ICommand cmd, object parameter)
        {
            execute(cmd, parameter);
        }

        #endregion
    }
}